package com.like.banzipao.server.util.roomstate.playroomstate

import com.like.banzipao.server.model.CompletedOrder
import com.like.banzipao.server.model.FriendType
import com.like.banzipao.server.model.Player
import com.like.banzipao.server.model.PlayerState
import com.like.banzipao.server.model.Poker
import com.like.banzipao.server.model.PokerState
import com.like.banzipao.server.model.Room

/**
 * 喊牌 2 vs 2 对决模式
 */
class TwoVsTwoRoomState(room: Room, private val onWin: () -> Unit) : PlayRoomState(room) {
    override fun onPlayPlayed(player: Player, nextPlayer: Player, curPlayedPokers: List<Poker>): Boolean {
        player.state = PlayerState.PLAY_PLAYED
        room.players.forEach {
            if (it?.user?.id != player.user.id) {
                it?.state = PlayerState.PLAYING
            }
        }
        curPlayedPokers.forEach {
            it.state = PokerState.PLAY_PLAYED
        }

        if (player.isAllPokersPlayed()) {
            val maxCompletedOrderOrdinal = room.players.maxOf {
                it!!.completedOrder.ordinal
            }
            player.completedOrder = CompletedOrder.entries[maxCompletedOrderOrdinal + 1]
        }

        if (!checkWin(player)) {
            player.nextValidPlayerTurn(PlayerState.PLAY_TURN)
            prePlayedPokers.clear()
            prePlayedPokers.addAll(curPlayedPokers)
            // 检查朋友关系。如果喊的牌出现了，就设置关系
            val hanPoker = room.players.firstOrNull { it?.hanPoker != null }?.hanPoker
            if (hanPoker != null && curPlayedPokers.contains(hanPoker)) {// 喊的牌出现了
                setFriendType()
            }
        } else {
            // 检查朋友关系。这里检查是因为有可能一局结束，喊的牌还没有出现。
            setFriendType()
            onWin()
        }
        return true
    }

    override fun onPlayPass(player: Player, nextPlayer: Player) {
        player.state = PlayerState.PLAY_PASS
        if (nextPlayer.winPoker()) {
            nextPlayer.getPokers().forEach {
                if (it.state == PokerState.PLAY_PLAYED) {
                    it.state = PokerState.PLAY_DECKS
                }
            }
            room.pokers.forEach {
                if (it.state == PokerState.PLAY_DECKS) {
                    it.state = PokerState.PLAY_GOT
                    it.holderUserId = nextPlayer.user.id
                }
            }
            player.nextValidPlayerTurn(PlayerState.PLAY_TURN_WIN)
            room.players.forEach {
                if (it?.state != PlayerState.PLAY_TURN_WIN) {
                    it?.state = PlayerState.PLAYING
                }
            }
            prePlayedPokers.clear()
        } else {
            player.nextValidPlayerTurn(PlayerState.PLAY_TURN)
        }
    }

    override fun getDealerUserId(): Int {
        return room.players.find {
            it?.completedOrder == CompletedOrder.ONE
        }?.user?.id ?: -1
    }

    override fun getIntegralChange(player: Player): Int {
        val completedOrderPlayer1 = room.players.find {
            it?.completedOrder == CompletedOrder.ONE
        }!!
        val completedOrderPlayer2 = room.players.find {
            it?.completedOrder == CompletedOrder.TWO
        }!!
        val guan = completedOrderPlayer1.friendTypeTemp == completedOrderPlayer2.friendTypeTemp
        return if (player.state == PlayerState.PLAY_WIN) {
            if (guan) 2 else 1
        } else {
            if (guan) -2 else -1
        }
    }

    private fun checkWin(player: Player): Boolean {
        // 合作的两家都出完本局就结束了。
        if (player.isAllPokersPlayed()) {
            if (player.completedOrder == CompletedOrder.TWO) {
                val completedOrderPlayer1 = room.players.find {
                    it?.completedOrder == CompletedOrder.ONE
                }!!
                if (completedOrderPlayer1.friendTypeTemp == player.friendTypeTemp) {
                    // 关了
                    room.players.forEach {
                        it ?: return@forEach
                        if (it.friendTypeTemp == player.friendTypeTemp) {
                            it.state = PlayerState.PLAY_WIN
                            it.integral += 2
                        } else {
                            it.state = PlayerState.PLAY_LOSE
                            it.integral -= 2
                        }
                    }
                    return true
                }
            } else if (player.completedOrder == CompletedOrder.FOUR) {
                // 比得牌数量
                var countA = 0
                var countB = 0
                room.players.forEach {
                    it ?: return@forEach
                    if (it.friendTypeTemp == FriendType.PARTY_A) {
                        countA += it.getPokers().count {
                            it.state == PokerState.PLAY_GOT
                        }
                    } else if (it.friendTypeTemp == FriendType.PARTY_B) {
                        countB += it.getPokers().count {
                            it.state == PokerState.PLAY_GOT
                        }
                    }
                }
                val winnerFriendType = if (countA > countB) {
                    FriendType.PARTY_A
                } else if (countA < countB) {
                    FriendType.PARTY_B
                } else {// 牌一样多就第一名那方赢
                    room.players.find {
                        it?.completedOrder == CompletedOrder.ONE
                    }!!.friendTypeTemp// 第一名
                }
                room.players.forEach {
                    it ?: return@forEach
                    if (it.friendTypeTemp == winnerFriendType) {
                        it.state = PlayerState.PLAY_WIN
                        it.integral += 1
                    } else {
                        it.state = PlayerState.PLAY_LOSE
                        it.integral -= 1
                    }
                }
                return true
            }
        }
        return false
    }

    /**
     * 设置朋友关系
     */
    private fun setFriendType() {
        if (room.players.filterNotNull().first().friendType == FriendType.NONE) {// 没有设置过关系
            room.players.forEach {
                it?.let {
                    it.friendType = it.friendTypeTemp
                }
            }
        }
    }
}